﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace iNet.Media.Imaging.Exif
{
	/// <summary>
	/// EXIF Tag 分類器。
	/// </summary>
	public class ExifTagClassifier
	{
		#region 靜態欄位
		static readonly Comparison<ExifTag> _TagComparison = (x, y) =>
		{
			return (x.ID - y.ID);
		};
        #endregion
		#region 欄位
		ReadOnlyCollection<ExifTag> _ExifIfd;
		ReadOnlyCollection<ExifTag> _GpsIfd;
		ReadOnlyCollection<ExifTag> _Ifd0;
		ReadOnlyCollection<ExifTag> _Ifd1;
		ReadOnlyCollection<ExifTag> _Ifd2;
		ReadOnlyCollection<ExifTag> _Ifd3;
		ReadOnlyCollection<ExifTag> _InteroperabilityIfd;
		ReadOnlyCollection<ExifTag> _MakerNote;
		ReadOnlyCollection<ExifTag> _SubIfd0;
		ReadOnlyCollection<ExifTag> _SubIfd1;
		ReadOnlyCollection<ExifTag> _UnclassifiedTags;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 ExifTagClassifier 執行個體。
		/// </summary>
		/// <param name="tags">EXIF Tag 集合。</param>
		/// <exception cref="ArgumentNullException">tags 為 Null (Visual Basic 為 Nothing)。</exception>
		public ExifTagClassifier(IEnumerable<ExifTag> tags)
		{
			//確認參數
			if (tags == null)
				throw new ArgumentNullException("tags");

			//分類
			this.Classify(tags);
		}
		#endregion
		#region Classify
		void Classify(IEnumerable<ExifTag> tags)
		{
			//分類
			List<ExifTag> exifIfd = new List<ExifTag>();
			List<ExifTag> gpsIfd = new List<ExifTag>();
			List<ExifTag> ifd0 = new List<ExifTag>();
			List<ExifTag> ifd1 = new List<ExifTag>();
			List<ExifTag> ifd2 = new List<ExifTag>();
			List<ExifTag> ifd3 = new List<ExifTag>();
			List<ExifTag> interopIfd = new List<ExifTag>();
			List<ExifTag> makerNote = new List<ExifTag>();
			List<ExifTag> subIfd0 = new List<ExifTag>();
			List<ExifTag> subIfd1 = new List<ExifTag>();
			List<ExifTag> unclassifiedTags = new List<ExifTag>();
			foreach (ExifTag tag in tags)
			{
				if (tag != null)
				{
					switch (tag.Ifd)
					{
						case Ifd.Ifd0:
							ifd0.Add(tag);
							break;
						case Ifd.Ifd1:
							ifd1.Add(tag);
							break;
						case Ifd.Ifd2:
							ifd2.Add(tag);
							break;
						case Ifd.Ifd3:
							ifd3.Add(tag);
							break;
						case Ifd.ExifIfd:
							exifIfd.Add(tag);
							break;
						case Ifd.GpsIfd:
							gpsIfd.Add(tag);
							break;
						case Ifd.InteroperabilityIfd:
							interopIfd.Add(tag);
							break;
						case Ifd.SubIfd0:
							subIfd0.Add(tag);
							break;
						case Ifd.SubIfd1:
							subIfd1.Add(tag);
							break;
						case Ifd.CanonMakerNote:
						case Ifd.NikonMakerNoteType3:
						case Ifd.PentaxMakerNote:
							if (makerNote.Count == 0 || makerNote[0].Ifd == tag.Ifd)
								makerNote.Add(tag);
							else
								goto default;
							break;
						default:
							unclassifiedTags.Add(tag);
							break;
					}
				}
			}

			//排序
			exifIfd.Sort(_TagComparison);
			gpsIfd.Sort(_TagComparison);
			ifd0.Sort(_TagComparison);
			ifd1.Sort(_TagComparison);
			ifd2.Sort(_TagComparison);
			ifd3.Sort(_TagComparison);
			interopIfd.Sort(_TagComparison);
			makerNote.Sort(_TagComparison);
			subIfd0.Sort(_TagComparison);
			subIfd1.Sort(_TagComparison);
			

			//建立物件
			_ExifIfd = new ReadOnlyCollection<ExifTag>(exifIfd);
			_GpsIfd = new ReadOnlyCollection<ExifTag>(gpsIfd);
			_Ifd0 = new ReadOnlyCollection<ExifTag>(ifd0);
			_Ifd1 = new ReadOnlyCollection<ExifTag>(ifd1);
			_Ifd2 = new ReadOnlyCollection<ExifTag>(ifd2);
			_Ifd3 = new ReadOnlyCollection<ExifTag>(ifd3);
			_InteroperabilityIfd = new ReadOnlyCollection<ExifTag>(interopIfd);
			_MakerNote = new ReadOnlyCollection<ExifTag>(makerNote);
			_SubIfd0 = new ReadOnlyCollection<ExifTag>(subIfd0);
			_SubIfd1 = new ReadOnlyCollection<ExifTag>(subIfd1);
			_UnclassifiedTags = new ReadOnlyCollection<ExifTag>(unclassifiedTags);
		}
		#endregion
		#region ExifIfd
		/// <summary>
		/// 取得屬於 EXIF IFD 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> ExifIfd
		{
			get
			{
				return _ExifIfd;
			}
		}
		#endregion
		#region GpsIfd
		/// <summary>
		/// 取得屬於 GPS IFD 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> GpsIfd
		{
			get
			{
				return _GpsIfd;
			}
		}
		#endregion
		#region Ifd0
		/// <summary>
		/// 取得屬於 IFD 0 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> Ifd0
		{
			get
			{
				return _Ifd0;
			}
		}
		#endregion
		#region Ifd1
		/// <summary>
		/// 取得屬於 IFD 1 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> Ifd1
		{
			get
			{
				return _Ifd1;
			}
		}
		#endregion
		#region Ifd2
		/// <summary>
		/// 取得屬於 IFD 2 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> Ifd2
		{
			get
			{
				return _Ifd2;
			}
		}
		#endregion
		#region Ifd3
		/// <summary>
		/// 取得屬於 IFD 3 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> Ifd3
		{
			get
			{
				return _Ifd3;
			}
		}
		#endregion
		#region InteroperabilityIfd
		/// <summary>
		/// 取得屬於 Interoperability IFD 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> InteroperabilityIfd
		{
			get
			{
				return _InteroperabilityIfd;
			}
		}
		#endregion
		#region MakerNote
		/// <summary>
		/// 取得屬於 MakerNote 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> MakerNote
		{
			get
			{
				return _MakerNote;
			}
		}
		#endregion
		#region SubIfd0
		/// <summary>
		/// 取得屬於 Sub IFD 0 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> SubIfd0
		{
			get
			{
				return _SubIfd0;
			}
		}
		#endregion
		#region SubIfd1
		/// <summary>
		/// 取得屬於 Sub IFD 1 的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> SubIfd1
		{
			get
			{
				return _SubIfd1;
			}
		}
		#endregion
		#region UnclassifiedTags
		/// <summary>
		/// 取得無法分類的 EXIF Tag 集合。
		/// </summary>
		public ReadOnlyCollection<ExifTag> UnclassifiedTags
		{
			get
			{
				return _UnclassifiedTags;
			}
		}
		#endregion
	}
}
